home *** CD-ROM | disk | FTP | other *** search
- # ****************************************************************************
- #
- # Frozen-Bubble Level Editor
- #
- # Copyright (c) 2002 - 2003 Kim Joham and David Joham <[k|d]joham@yahoo.com>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License version 2, as
- # published by the Free Software Foundation.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- #
- #
- # *****************************************************************************
- #
- # Design & Programming by Kim Joham and David Joham, October 2002 - January 2003
- #
- # pencil icon taken from the GIMP project
- #
- #
- # Integration to Frozen-Bubble by Guillaume Cottenceau - change a few styles
- # things, fix a few bugs, add a few features
- #
- #
- # *****************************************************************************
-
- package FBLE;
-
- use POSIX;
- use SDL;
- use SDL::App;
- use SDL::Surface;
- use SDL::Event;
- use SDL::Cursor;
- use SDL::Font;
- use SDL::Mixer;
-
- use fb_stuff;
- use fbsyms;
-
- use strict;
- our ($NUM_ROWS, $NUM_BUBBLES_AVAIL,
- $BUBBLES_PER_ROW, $BUBBLE_OPTION_SEPARATION, $BUBBLE_OPTION_INIT_X,
- $ALPHA_BUBBLE_NO, $ALPHA_BUBBLE_YES, $WOOD_WIDTH, $WOOD_PLANK_HEIGHT,
- $LEFT_WOOD_X, $RIGHT_WOOD_X, $BUBBLE_WOOD_Y, $NAV_WOOD_Y, $LEVELSET_WOOD_Y,
- $LEVEL_WOOD_Y, $colourblind, $app, $font, %bubble_rects, %bubble_hash, $color,
- $action, $previousx, $previousy, $background, $highlight,
- $highlighted_option, $curr_level, $displaying_dialog, $new_ls_name_text, $surface_dialog,
- $levelset_name, $list_browser_file_start_offset, $list_browser_highlight_offset,
- $surf_shrink, @file_browser_screenshots, $deleted_current_levelset,
- $modified_levelset, $modified_levelset_action, $button_hold, $command_line_fullscreen, %rect);
-
-
- $NUM_ROWS = 10;
- $POS_1P{bottom_limit} = $POS_1P{init_top_limit} + $NUM_ROWS * $ROW_SIZE;
- $NUM_BUBBLES_AVAIL = 8;
- $BUBBLES_PER_ROW = 3;
- $BUBBLE_OPTION_SEPARATION = 8;
- $BUBBLE_OPTION_INIT_X = 18;
- $ALPHA_BUBBLE_NO = 0;
- $ALPHA_BUBBLE_YES = 1;
-
- $WOOD_WIDTH = 150;
- $WOOD_PLANK_HEIGHT = 40;
- $LEFT_WOOD_X = 2;
- $RIGHT_WOOD_X = 488;
- $BUBBLE_WOOD_Y = 33;
- $NAV_WOOD_Y = 209;
- $LEVELSET_WOOD_Y = 30;
- $LEVEL_WOOD_Y = 249;
-
- $highlighted_option = '';
- $previousx = -1;
- $previousy = -1;
- $displaying_dialog = '';
- $deleted_current_levelset = 0;
- $button_hold = 0;
-
-
- #- ----------- bubbles processing/drawing -----------------------------------------
-
- # subroutine to calculate the left corner x of the given bubble option column (based on 0 start)
- sub bubble_optionx {
- my ($col) = @_;
- return $BUBBLE_OPTION_INIT_X + $col * ($BUBBLE_SIZE + $BUBBLE_OPTION_SEPARATION);
- }
-
- # subroutine to calculate the left corner y of the given bubble option row (based on 0 start)
- sub bubble_optiony {
- my ($row) = @_;
- return $BUBBLE_WOOD_Y + $WOOD_PLANK_HEIGHT + $row * ($BUBBLE_SIZE + $BUBBLE_OPTION_SEPARATION);
- }
-
- # subroutine to get the column
- sub get_col {
- my ($x, $y) = @_;
- if (even(get_row($y))) {
- return floor(($x-$POS_1P{p1}{left_limit})/$BUBBLE_SIZE);
-
- } elsif ($POS_1P{p1}{left_limit} + $BUBBLE_SIZE/2 <= $x && $x < $POS_1P{p1}{right_limit} - $BUBBLE_SIZE/2) {
- return floor(($x-($POS_1P{p1}{left_limit}+$BUBBLE_SIZE/2))/$BUBBLE_SIZE);
-
- } else {
- return -1;
- }
- }
-
- # subroutine to get the row
- sub get_row {
- my ($y) = @_;
- return floor(($y-$POS_1P{init_top_limit})/$ROW_SIZE);
- }
-
- # subroutine to draw bubbles
- sub draw_bubble {
- my ($bubbleid, $x, $y, $alpha, $surface_tmp, $ignore_update) = @_;
- my ($bubble);
-
- $surface_tmp or $surface_tmp = $app;
- $bubble = SDL::Surface->new(-name => "$FPATH/gfx/balls/bubble-".($colourblind && 'colourblind-')."$bubbleid.gif");
-
- $bubble_rects{$x}{$y} = SDL::Rect->new(-x => $x, '-y' => $y, -width => $bubble->width, -height => $bubble->height);
-
- $alpha and $bubble->set_alpha(SDL_SRCALPHA, 0x66);
-
- $bubble->blit(NULL, $surface_tmp, $bubble_rects{$x}{$y});
- $ignore_update or $surface_tmp->update($bubble_rects{$x}{$y});
- }
-
- # subroutine to erase bubble
- sub erase_bubble {
- my ($x, $y) = @_;
- $background->blit($bubble_rects{$x}{$y}, $app, $bubble_rects{$x}{$y});
- #- redraw close bubbles because the rectangular blit of the previous statement erased a bit of them
- my $DISTANCE_CLOSE_SQRED = sqr($BUBBLE_SIZE*1.1);
- foreach my $x_ (keys %bubble_rects) {
- foreach my $y_ (%{$bubble_rects{$x_}}) {
- $y != $y_ && sqr($x-$x_) + sqr($y-$y_) <= $DISTANCE_CLOSE_SQRED or next;
- if ($bubble_hash{$curr_level}{my $col = get_col($x_, $y_)}{my $row = get_row($y_)} =~ /^\d+$/) {
- draw_bubble($bubble_hash{$curr_level}{$col}{$row} + 1, $x_, $y_, $ALPHA_BUBBLE_NO, undef, 1);
- }
- }
- }
- $app->update($bubble_rects{$x}{$y});
- }
-
- # subroutine to place a bubble
- sub place_bubble {
- my ($x, $y, $alpha, $button) = @_;
- my $col = get_col($x, $y);
- my $row = get_row($y);
- $y = $row * $ROW_SIZE + $POS_1P{init_top_limit};
- if ($col != -1) {
- if (even($row)) {
- $x = get_col($x, $y) * $BUBBLE_SIZE + $POS_1P{p1}{left_limit};
- } else {
- $x = $col * $BUBBLE_SIZE + $POS_1P{p1}{left_limit} + $BUBBLE_SIZE/2;
- }
- if ($action eq 'erase' || $button >= 3) { #- when in motion, the right button is reported as button 4 !?
- if (($previousx != $x || $previousy != $y) && $previousx != -1 && $previousy != -1
- && $bubble_hash{$curr_level}{get_col($previousx, $previousy)}{get_row($previousy)} ne '-') {
- draw_bubble($bubble_hash{$curr_level}{get_col($previousx, $previousy)}{get_row($previousy)} + 1,
- $previousx, $previousy, $ALPHA_BUBBLE_NO);
- }
- if ($bubble_rects{$x}{$y}) {
- if ($alpha && $bubble_hash{$curr_level}{$col}{$row} ne '-') {
- if ($previousx != $x || $previousy != $y) {
- erase_bubble($x, $y);
- draw_bubble($bubble_hash{$curr_level}{$col}{$row} + 1, $x, $y, $alpha);
- }
- $previousx = $x;
- $previousy = $y;
- } else {
- $bubble_hash{$curr_level}{$col}{$row} = '-';
- erase_bubble($x, $y);
- }
- }
- } elsif ($action eq 'add') {
- if ($alpha) {
- if ($previousx != $x || $previousy != $y) {
- if ($previousx != -1 && $previousy != -1) {
- if ($bubble_hash{$curr_level}{get_col($previousx, $previousy)}{get_row($previousy)} eq '-') {
- erase_bubble($previousx, $previousy);
- } else {
- draw_bubble($bubble_hash{$curr_level}{get_col($previousx, $previousy)}{get_row($previousy)} + 1,
- $previousx, $previousy, $ALPHA_BUBBLE_NO);
- }
- }
- draw_bubble($color, $x, $y, $alpha);
- $previousx = $x;
- $previousy = $y;
- }
- } else {
- $bubble_hash{$curr_level}{$col}{$row} = $color - 1;
- draw_bubble($color, $x, $y, $alpha);
- }
- }
- }
- }
-
-
- #- ----------- actions routing -----------------------------------------
-
- # subroutine to change my color
- sub change_color {
- my ($new_color) = @_;
- $color = $new_color;
- $action = 'add';
-
- draw_bubble($color,
- $POS_1P{next_bubble}{x} + $POS_1P{p1}{left_limit},
- $POS_1P{next_bubble}{y},$ALPHA_BUBBLE_NO); #- }}})
- }
-
- sub highlight_option {
- my ($option, $x, $y) = @_;
-
- unhighlight_option($option);
- if ($option ne $highlighted_option) {
- $highlighted_option = $option;
- $option =~ s/bubble-(\d+)/$1/;
-
- if (0 < $option && $option <= $NUM_BUBBLES_AVAIL) {
- $highlight->blit($rect{bubble_option_highlight}, $app, $bubble_rects{$x}{$y});
- $app->update($bubble_rects{$x}{$y});
-
- } elsif ($option eq 'erase') {
- $highlight->blit($rect{bubble_option_highlight}, $app, $rect{erase});
- $app->update($rect{erase});
-
- } elsif ($option =~ m/arrow/){
- eval "print_dialog_$option(1)";
-
- } else {
- eval "print_$option".'_text(1)';
- }
- }
-
- }
-
- sub unhighlight_option {
- # note: will only have x and y for bubbles and erase
- my ($no_highlight) = @_;
- my ($col, $row);
-
- # don't unhighlight currently highlighted option because it will cause flashing
- if ($highlighted_option ne '' && $highlighted_option ne $no_highlight) {
- $highlighted_option =~ s/bubble-(\d+)/$1/;
- if (0 < $highlighted_option && $highlighted_option <= $NUM_BUBBLES_AVAIL) {
- $col = ($highlighted_option - 1 ) % $BUBBLES_PER_ROW;
- $row = floor(($highlighted_option - 1 ) / $BUBBLES_PER_ROW);
-
- my $rect = $bubble_rects{bubble_optionx($col)}{bubble_optiony($row)};
- $background->blit($rect, $app, $rect);
- $app->update($rect);
-
- add_bubble_option($highlighted_option, $col, $row);
-
- } elsif ($highlighted_option eq 'erase') {
- $background->blit($rect{erase}, $app, $rect{erase});
- $app->update($rect{erase});
-
- add_erase_option();
-
- } elsif ($highlighted_option =~ m/arrow/) {
- eval "print_dialog_$highlighted_option(0)";
-
- } else {
- eval "print_$highlighted_option".'_text(0)';
- }
-
- $highlighted_option = '';
- }
-
- }
-
- # subroutine to decide what my mouse is telling me to do
- sub choose_action {
- my ($x, $y, $caller, $button) = @_;
-
- # are we over the drawing area?
- if ($POS_1P{p1}{left_limit} <= $x && $x < $POS_1P{p1}{right_limit} && $POS_1P{init_top_limit} <= $y && $y < $POS_1P{bottom_limit}) {
- if ($caller eq 'motion' && $button_hold == 0) {
- place_bubble($x, $y, $ALPHA_BUBBLE_YES, $button);
- } elsif ($button_hold == 1) {
- place_bubble($x, $y, $ALPHA_BUBBLE_NO, $button);
- $modified_levelset = 1;
- } else { # $caller is 'button'
- place_bubble($x, $y, $ALPHA_BUBBLE_NO, $button);
- $modified_levelset = 1;
- }
-
- # we will want to remove bubble highlight if we go out of our drawing area
- } elsif ($previousx != -1 && $previousy != -1) {
- if ($bubble_hash{$curr_level}{get_col($previousx, $previousy)}{get_row($previousy)} eq '-') {
- erase_bubble($previousx, $previousy);
- } else {
- draw_bubble($bubble_hash{$curr_level}{get_col($previousx, $previousy)}{get_row($previousy)} + 1,
- $previousx, $previousy, $ALPHA_BUBBLE_NO);
- }
- # make sure that when we come back into the drawing area, we immediatly start
- # doing our highlights - if we don't do this, you don't get a highlight
- # if you come back to the same spot that you left
- $previousx = -1;
- $previousy = -1;
- }
-
- # selecting a bubble or erase bubble??
- if ($y >= $BUBBLE_WOOD_Y + $WOOD_PLANK_HEIGHT && $y <= $BUBBLE_WOOD_Y + 4 * $WOOD_PLANK_HEIGHT
- && $x > $BUBBLE_OPTION_INIT_X - $BUBBLE_OPTION_SEPARATION/2
- && $x <= $BUBBLE_OPTION_INIT_X + $BUBBLES_PER_ROW * ($BUBBLE_SIZE + $BUBBLE_OPTION_SEPARATION) - $BUBBLE_OPTION_SEPARATION/2) {
- my $col = ceil(($x - $BUBBLE_OPTION_INIT_X + $BUBBLE_OPTION_SEPARATION/2) / ($BUBBLE_SIZE + $BUBBLE_OPTION_SEPARATION));
- my $row = ceil(($y - ($BUBBLE_WOOD_Y + $WOOD_PLANK_HEIGHT) + $BUBBLE_OPTION_SEPARATION/2) / ($BUBBLE_SIZE + $BUBBLE_OPTION_SEPARATION));
-
- my $color_tmp = $BUBBLES_PER_ROW * ($row - 1) + $col;
- if (0 < $color_tmp && $color_tmp <= $NUM_BUBBLES_AVAIL) {
- highlight_option("bubble-$color_tmp", bubble_optionx($col - 1), bubble_optiony($row - 1));
- $caller eq 'button' and change_color($color_tmp);
- } elsif ($color_tmp == $NUM_BUBBLES_AVAIL + 1) {
- highlight_option('erase');
- if ($caller eq 'button') {
- $action = 'erase';
- erase_bubble($POS_1P{next_bubble}{x} + $POS_1P{p1}{left_limit}, $POS_1P{next_bubble}{'y'});
- }
- }
-
- # check if over navigation options
- } elsif ($LEFT_WOOD_X <= $x && $x <= $WOOD_WIDTH && $rect{prev}->y <= $y && $y <= $rect{last}->y + $rect{last}->height) {
- my @nav_options = ({ name => 'prev',
- unhighlight => $curr_level == 1,
- action => sub { if ($curr_level != 1) {
- prev_level();
- $curr_level == 1 and unhighlight_option();
- } } },
- { name => 'next',
- unhighlight => $curr_level == keys %bubble_hash,
- action => sub { if ($curr_level != keys %bubble_hash) {
- next_level();
- $curr_level == keys %bubble_hash and unhighlight_option();
- } } },
- { name => 'first',
- unhighlight => $curr_level == 1,
- action => sub { if ($curr_level != 1) {
- first_level();
- unhighlight_option();
- } } },
- { name => 'last',
- unhighlight => $curr_level == keys %bubble_hash,
- action => sub { if ($curr_level != keys %bubble_hash) {
- last_level();
- unhighlight_option();
- } } },
- );
-
- foreach (@nav_options) {
- if ($rect{$_->{name}}->y <= $y && $y <= $rect{$_->{name}}->y + $rect{$_->{name}}->height) {
- if ($_->{unhighlight}) {
- unhighlight_option();
- } else {
- highlight_option($_->{name});
- }
- $caller eq 'button' and $_->{action}->();
- }
- }
-
- # check if over levelset options
- } elsif ($RIGHT_WOOD_X <= $x && $x <= $RIGHT_WOOD_X + $WOOD_WIDTH
- && $y >= $rect{ls_new}->y && $y <= $rect{ls_delete}->y + $rect{ls_delete}->height) {
- my @ls_options = ({ name => 'ls_new', action => sub { create_new_levelset_dialog() } },
- { name => 'ls_open', action => sub { create_open_levelset_dialog() } },
- { name => 'ls_save', action => sub { save_file() } },
- { name => 'ls_delete', action => sub { create_delete_levelset_dialog() } });
- foreach (@ls_options) {
- if ($y >= $rect{$_->{name}}->y && $y <= $rect{$_->{name}}->y + $rect{$_->{name}}->height) {
- highlight_option($_->{name});
- $caller eq 'button' and $_->{action}->();
- }
- }
-
- # check if over level options
- } elsif ($RIGHT_WOOD_X <= $x && $x <= $RIGHT_WOOD_X + $WOOD_WIDTH
- && $y >= $rect{lvl_insert}->y && $y <= $rect{lvl_delete}->y + $rect{lvl_delete}->height) {
- my @lvl_options = ({ name => 'lvl_insert', action => sub { insert_level() } },
- { name => 'lvl_append', action => sub { append_level() } },
- { name => 'lvl_delete', action => sub { delete_level(); load_level() } });
- foreach (@lvl_options) {
- if ($y >= $rect{$_->{name}}->y && $y <= $rect{$_->{name}}->y + $rect{$_->{name}}->height) {
- highlight_option($_->{name});
- $caller eq 'button' and $_->{action}->();
- }
- }
-
- # not over an option so I may need to unhighlight
- } else {
- unhighlight_option();
- }
-
- }
-
- # subroutine to return the list of levelsets in $FBLEVELS
- sub get_levelset_list {
- my @levelsets = map { $_ =~ s{^.*/(.*)$}{$1}; $_; } sort(glob("$FBLEVELS/*"));
- $displaying_dialog eq 'ls_delete' and @levelsets = difference2(\@levelsets,['default-levelset']);
- return @levelsets;
- }
-
- sub betw {
- my ($val, $min, $max) = @_;
- $val > $min && $val < $max;
- }
-
- # subroutine to decide what my mouse is telling me to do in the dialog box
- sub choose_dialog_action {
- my ($x, $y, $caller) = @_;
- my ($ok_rect, $cancel_rect, $surface_tmp);
-
- # todo - can we get this info somewhere else in a better way?
- $surface_tmp = SDL::Surface->new(-name => "$FPATH/gfx/list_arrow_up.png");
-
- $rect{middle} = get_dialog_rect();
- # over left button
- if (betw($x, $rect{middle}->x, $rect{middle}->x + $rect{middle}->width/2)
- && betw($y, $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT, $rect{middle}->y + $rect{middle}->height)) {
- if (member($displaying_dialog, qw(ls_play ls_nothing_to_delete ls_open_ok_only ls_new_ok_only))) {
- # this dialog does not have a left button. return
- unhighlight_option();
- return 1;
- }
-
- if ($displaying_dialog eq 'ls_new' && is_ok_filename() == 1) {
- highlight_option('ok');
- } else {
- unhighlight_option('ok');
- }
-
- $displaying_dialog ne 'ls_new' and highlight_option('ok');
-
- if ($caller eq 'button') {
- if ($displaying_dialog eq 'ls_new' && is_ok_filename() == 1) {
- remove_dialog();
- create_new_levelset();
- } elsif ($displaying_dialog eq 'ls_open') {
- open_levelset();
- } elsif ($displaying_dialog eq 'ls_delete') {
- delete_levelset();
- } elsif ($displaying_dialog eq 'ls_deleted_current') {
- create_open_levelset_dialog_ok_only();
- } elsif ($displaying_dialog eq 'ls_save_changes') {
- save_file();
- $displaying_dialog = '';
- eval($modified_levelset_action);
- }
- }
-
- # over right button
- } elsif (betw($x, $rect{middle}->x + $rect{middle}->width/2, $rect{middle}->x + $rect{middle}->width)
- && betw($y, $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT, $rect{middle}->y + $rect{middle}->height)) {
- if (member($displaying_dialog, qw(ls_play ls_nothing_to_delete ls_open_ok_only ls_new_ok_only))) {
- if ($displaying_dialog eq 'ls_new_ok_only' && is_ok_filename() == 1) {
- highlight_option('ok_right');
- } else {
- unhighlight_option('ok_right');
- }
-
- if ($displaying_dialog eq 'ls_nothing_to_delete') {
- highlight_option('ok_right');
- if ($caller eq 'button') {
- $displaying_dialog = '';
- remove_dialog();
- }
- }
-
- $displaying_dialog ne 'ls_new_ok_only' and highlight_option('ok_right');
-
- if ($caller eq 'button') {
- if ($displaying_dialog eq 'ls_play') {
- my @levelsets = get_levelset_list();
- $modified_levelset_action = "return $levelsets[$list_browser_highlight_offset]";
- return 1;
-
- } elsif ($displaying_dialog eq 'ls_open_ok_only') {
- remove_dialog();
- $displaying_dialog = '';
- open_levelset();
-
- } elsif ($displaying_dialog eq 'ls_new_ok_only' && is_ok_filename() == 1) {
- remove_dialog();
- create_new_levelset();
- }
- }
- } else {
- highlight_option('cancel');
- if ($caller eq 'button') {
- if ($displaying_dialog eq 'ls_open' && $deleted_current_levelset == 1) {
- remove_dialog();
- create_deleted_current_levelset_dialog();
-
- } elsif ($displaying_dialog eq 'ls_deleted_current') {
- $levelset_name = 'default-levelset';
- %bubble_hash = read_file($levelset_name);
- $curr_level = 1;
- $displaying_dialog = '';
- remove_dialog();
- load_level();
- print_levelset_name();
- $deleted_current_levelset = 0;
-
- } elsif ($displaying_dialog eq 'ls_save_changes') {
- $displaying_dialog = '';
- eval($modified_levelset_action);
-
- } else {
- remove_dialog();
- }
- }
- }
-
- } elsif (member($displaying_dialog, qw(ls_open_ok_only ls_open ls_delete ls_play))) {
- if (betw($x, $rect{middle}->x + 4 * $rect{middle}->width/6, $rect{middle}->x + 4 * $rect{middle}->width/6 + $surface_tmp->width)) {
- my @arrows = ($rect{dialog_file_list}->y + 2,
- $rect{dialog_file_list}->y + $rect{dialog_file_list}->height - $surface_tmp->height - 2);
- if (betw($y, $arrows[0], $arrows[0] + $surface_tmp->height)) {
- $caller eq 'button' and display_levelset_list_browser($list_browser_file_start_offset - 1, $list_browser_highlight_offset);
- highlight_option('list_arrow_up');
-
- } elsif (betw($y, $arrows[1], $arrows[1] + $surface_tmp->height)) {
- $caller eq 'button' and display_levelset_list_browser($list_browser_file_start_offset + 1, $list_browser_highlight_offset);
- highlight_option('list_arrow_down');
-
- } else {
- unhighlight_option();
- }
- } elsif (betw($x, $rect{dialog_file_list}->x, $rect{dialog_file_list}->x + $rect{dialog_file_list}->width)
- && betw($y, $rect{dialog_file_list}->y, $rect{dialog_file_list}->y + $rect{dialog_file_list}->height)) {
- if ($caller eq 'button') {
- if ($y < $rect{dialog_file_list}->y + 25) {
- display_levelset_list_browser($list_browser_file_start_offset, $list_browser_file_start_offset);
- } elsif ($y < $rect{dialog_file_list}->y + 2 * 25) {
- display_levelset_list_browser($list_browser_file_start_offset, $list_browser_file_start_offset + 1);
- } elsif ($y < $rect{dialog_file_list}->y + 3 * 25) {
- display_levelset_list_browser($list_browser_file_start_offset, $list_browser_file_start_offset + 2);
- } else {
- display_levelset_list_browser($list_browser_file_start_offset, $list_browser_file_start_offset + 3);
- }
- }
- } else {
- unhighlight_option();
- }
- } else {
- unhighlight_option();
- }
- }
-
- # react to user's keyboard and mouse events
- sub handle_events {
- my $event = SDL::Event->new;
-
- while (1) {
- $event->pump;
- if ($event->poll != 0) {
-
- if ($event->type == SDL_MOUSEMOTION) {
- if ($displaying_dialog eq '') {
- choose_action($event->button_x, $event->button_y, 'motion', $event->button); #- , )
- } else {
- choose_dialog_action($event->button_x, $event->button_y, 'motion'); #- ,, )
- }
- $app->flip;
-
- } elsif ($event->type == SDL_MOUSEBUTTONDOWN) {
- $button_hold = 1;
- if ($displaying_dialog eq '') {
- choose_action($event->button_x, $event->button_y, 'button', $event->button); #- , )
- } else {
- choose_dialog_action($event->button_x, $event->button_y, 'button'); #- ,, )
- }
- $app->flip;
-
- } elsif ($event->type == SDL_MOUSEBUTTONUP) {
- $button_hold = 0;
-
- } elsif ($event->type == SDL_KEYDOWN) {
- if ($displaying_dialog eq '') {
- if ($event->key_sym == SDLK_ESCAPE() || $event->key_sym == SDLK_q() ) {
- if ($modified_levelset == 1) {
- $modified_levelset_action = '$modified_levelset_action = "return 1"';
- create_save_changes_dialog();
- } else {
- return 1;
- }
- }
- $event->key_sym == SDLK_LEFT() and prev_level();
- $event->key_sym == SDLK_RIGHT() and next_level();
- $event->key_sym == SDLK_UP() and first_level();
- $event->key_sym == SDLK_DOWN() and last_level();
- $event->key_sym == SDLK_a() and append_level();
- $event->key_sym == SDLK_d() and do { delete_level(); FBLE::load_level() };
- $event->key_sym == SDLK_f() and $app->fullscreen;
- $event->key_sym == SDLK_h() and prev_level();
- $event->key_sym == SDLK_i() and insert_level();
- $event->key_sym == SDLK_l() and next_level();
- $event->key_sym == SDLK_n() and next_level();
- $event->key_sym == SDLK_o() and create_open_levelset_dialog();
- $event->key_sym == SDLK_p() and prev_level();
- $event->key_sym == SDLK_s() and save_file();
- $event->key_sym == SDLK_RIGHTBRACKET() and move_level_right();
- $event->key_sym == SDLK_LEFTBRACKET() and move_level_left();
- $event->key_sym == SDLK_j() and do {
- my $number;
- while (1) {
- $event->pump;
- if ($event->poll != 0) {
- if ($event->type == SDL_KEYDOWN) {
- my $k = $event->key_sym;
- if ($k >= SDLK_0() && $k <= SDLK_9()) {
- $number .= $k-SDLK_0();
- }
- $k == SDLK_ESCAPE() and goto jump_end;
- $k == SDLK_RETURN() || $k == SDLK_KP_ENTER and goto jump_ok;
- }
- }
- $app->delay(1);
- }
- jump_ok:
- jump_to_level($number);
- jump_end:
- };
- if ((($highlighted_option eq 'prev' || $highlighted_option eq 'first') && $curr_level == 1)
- || (($highlighted_option eq 'next' || $highlighted_option eq 'last') && $curr_level == keys %bubble_hash)) {
- unhighlight_option();
- }
- } elsif (member($displaying_dialog, qw(ls_new ls_new_ok_only))) {
- print_new_ls_name($event->key_sym);
- } elsif ($displaying_dialog eq 'ls_open') {
- if ($event->key_sym() == SDLK_RETURN() || $event->key_sym() == SDLK_KP_ENTER()) {
- highlight_option('ok');
- $app->delay(200);
- open_levelset();
- } elsif ($event->key_sym() == SDLK_ESCAPE()) {
- highlight_option('cancel');
- $app->delay(200);
- remove_dialog();
- if ($deleted_current_levelset == 1) {
- create_deleted_current_levelset_dialog();
- }
- } elsif ($event->key_sym() == SDLK_DOWN()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset + 1, $FBLE::list_browser_highlight_offset + 1);
- } elsif ($event->key_sym() == SDLK_UP()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset - 1, $FBLE::list_browser_highlight_offset - 1);
- }
- } elsif ($displaying_dialog eq 'ls_open_ok_only') {
- if ($event->key_sym() == SDLK_RETURN() || $event->key_sym() == SDLK_KP_ENTER()) {
- highlight_option('ok_right');
- $app->delay(200);
- open_levelset();
- } elsif ($event->key_sym() == SDLK_DOWN()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset + 1, $FBLE::list_browser_highlight_offset + 1);
- } elsif ($event->key_sym() == SDLK_UP()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset - 1, $FBLE::list_browser_highlight_offset - 1);
- }
- } elsif ($displaying_dialog eq 'ls_play') {
- if ($event->key_sym == SDLK_RETURN() || $event->key_sym == SDLK_KP_ENTER()) {
- highlight_option('ok_right');
- $app->delay(200);
- my (@levelsets);
- @levelsets = get_levelset_list();
- $displaying_dialog = '';
- return $levelsets[$list_browser_highlight_offset];
- } elsif ($event->key_sym() == SDLK_DOWN()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset + 1, $FBLE::list_browser_highlight_offset + 1);
- } elsif ($event->key_sym() == SDLK_UP()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset - 1, $FBLE::list_browser_highlight_offset - 1);
- }
- } elsif ($displaying_dialog eq 'ls_delete') {
- if ($event->key_sym() == SDLK_RETURN() || $event->key_sym() == SDLK_KP_ENTER()) {
- highlight_option('ok');
- $app->delay(200);
- delete_levelset();
- } elsif ($event->key_sym() == SDLK_ESCAPE()) {
- highlight_option('cancel');
- $app->delay(200);
- remove_dialog();
- } elsif ($event->key_sym() == SDLK_DOWN()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset + 1, $FBLE::list_browser_highlight_offset + 1);
- } elsif ($event->key_sym() == SDLK_UP()) {
- display_levelset_list_browser($FBLE::list_browser_file_start_offset - 1, $FBLE::list_browser_highlight_offset - 1);
- }
- } elsif ($displaying_dialog eq 'ls_deleted_current') {
- if ($event->key_sym() == SDLK_RETURN() || $event->key_sym() == SDLK_KP_ENTER() ) {
- highlight_option('ok');
- $app->delay(200);
- remove_dialog();
- create_open_levelset_dialog_ok_only();
- } elsif ($event->key_sym() == SDLK_ESCAPE()) {
- highlight_option('cancel');
- $app->delay(200);
- $levelset_name = 'default-levelset';
- %bubble_hash = read_file($levelset_name);
- $curr_level = 1;
- $displaying_dialog = '';
- remove_dialog();
- load_level();
- print_levelset_name();
- $deleted_current_levelset = 0;
- }
- } elsif ($displaying_dialog eq 'ls_nothing_to_delete') {
- if ($event->key_sym() == SDLK_RETURN() || $event->key_sym() == SDLK_KP_ENTER()) {
- highlight_option('ok_right');
- $app->delay(200);
- $displaying_dialog = '';
- remove_dialog();
- }
- } elsif ($displaying_dialog eq 'ls_save_changes') {
- if ($event->key_sym() == SDLK_RETURN() || $event->key_sym() == SDLK_KP_ENTER() ) {
- highlight_option('ok');
- $app->delay(200);
- save_file();
- $displaying_dialog = '';
- eval($modified_levelset_action);
- } elsif ($event->key_sym() == SDLK_ESCAPE()) {
- highlight_option('cancel');
- $app->delay(200);
- $displaying_dialog = '';
- eval($modified_levelset_action);
- }
- }
-
- $app->flip;
-
- } elsif ($event->type == SDL_QUIT) {
- if ($displaying_dialog eq '') {
- if ($modified_levelset == 1) {
- $modified_levelset_action = '$modified_levelset_action = "return 1"';
- create_save_changes_dialog();
- $app->flip;
- } else {
- return 1;
- }
- }
- }
-
- if ($modified_levelset_action =~ /return (\S*)/ && $displaying_dialog ne 'ls_save_changes') {
- my $return_value = $1;
- $displaying_dialog = '';
- $modified_levelset_action = '';
- return $1;
- }
-
- } else {
- $app->delay(1);
- }
-
- }
- }
-
-
- #- ----------- dialogs -----------------------------------------
-
- # subroutine to get the rect where the promt will go
- sub get_dialog_rect {
- SDL::Rect->new(-x => $background->width/2 - $surface_dialog->width/2,
- '-y' => $background->height/2 - $surface_dialog->height/2,
- -width => $surface_dialog->width, -height => $surface_dialog->height);
- }
-
- sub create_dialog_base {
- my ($title_text) = @_;
-
- unhighlight_option();
- $surface_dialog = SDL::Surface->new(-name => "$FPATH/gfx/menu/void_panel.png");
-
- $rect{dialog} = SDL::Rect->new(-x => 0, '-y' => 0, -width => $surface_dialog->width, -height => $surface_dialog->height);
- $rect{middle} = get_dialog_rect();
-
- $surface_dialog->blit($rect{dialog}, $app, $rect{middle});
-
- $app->print($rect{middle}->x + $rect{middle}->width/2 - 12 * length($title_text)/2, $rect{middle}->y + 5, uc($title_text));
- }
-
- # sub to create a blank dialog on the screen
- sub create_dialog {
- my ($title_text) = @_;
- create_dialog_base($title_text);
- print_cancel_text(0);
- print_ok_text(0);
-
- }
-
- sub remove_dialog {
- $rect{middle} = SDL::Rect->new(-x => $background->width/2 - $surface_dialog->width/2,
- '-y' => $background->height/2 - $surface_dialog->height/2,
- -width => $surface_dialog->width, -height => $surface_dialog->height);
- $background->blit($rect{middle}, $app, $rect{middle});
- $app->update;
-
- # update the screen
- load_level();
- $displaying_dialog = '';
- }
-
- # subroutine to ask the user what to do if they delete the current levelset
- sub create_deleted_current_levelset_dialog {
- $displaying_dialog = 'ls_deleted_current';
- $deleted_current_levelset = 1;
- create_dialog('DELETED CURRENT LEVELSET');
- $rect{middle} = get_dialog_rect();
- $app->print($rect{middle}->x + 25, $rect{middle}->y + 15 + $WOOD_PLANK_HEIGHT, "PRESS \"OK\" TO CHOOSE");
- $app->print($rect{middle}->x + 25, $rect{middle}->y + 35 + $WOOD_PLANK_HEIGHT, "ANOTHER LEVELSET TO OPEN");
- $app->print($rect{middle}->x + 25, $rect{middle}->y + 3 * $WOOD_PLANK_HEIGHT, "PRESS \"CANCEL\" TO OPEN");
- $app->print($rect{middle}->x + 25, $rect{middle}->y + 25 + 3* $WOOD_PLANK_HEIGHT, "THE DEFAULT LEVELSET");
-
- }
-
- # subroutine to create a delete levelset dialog
- sub create_delete_levelset_dialog {
- if (all($FBLEVELS) > 1) {
- $displaying_dialog = 'ls_delete';
- create_dialog('SELECT LEVELSET TO DELETE');
- $list_browser_highlight_offset = -1;
- $list_browser_file_start_offset = -1;
- display_levelset_list_browser(0, 0);
- } else {
- $displaying_dialog = 'ls_nothing_to_delete';
- create_ok_dialog('NO LEVELSET TO DELETE');
- $rect{middle} = get_dialog_rect();
- $app->print($rect{middle}->x + 50, $rect{middle}->y + 30 + $WOOD_PLANK_HEIGHT, "THERE ARE NO CUSTOM");
- $app->print($rect{middle}->x + 50, $rect{middle}->y + 55 + $WOOD_PLANK_HEIGHT, "LEVELSETS TO DELETE.");
- $app->print($rect{middle}->x + 40, $rect{middle}->y + 125 + $WOOD_PLANK_HEIGHT, "PRESS \"OK\" TO CONTINUE");
- }
- }
-
- # subroutine to create a new levelset dialog. This dialog asks for the name of the new levelset
- sub create_new_levelset_dialog {
- if ($modified_levelset == 1) {
- $modified_levelset_action = 'create_new_levelset_dialog_ok_only()';
- create_save_changes_dialog();
- } else {
- $displaying_dialog = 'ls_new';
- # create the blank dialog with the title of "enter new levelset name"
- create_dialog('ENTER NEW LEVELSET NAME');
- # inialize the new levelset name
- $new_ls_name_text = '';
- }
-
- }
-
- sub create_new_levelset_dialog_ok_only {
- $displaying_dialog = 'ls_new_ok_only';
- create_ok_dialog('ENTER NEW LEVELSET NAME');
- $new_ls_name_text = '';
- }
-
- # sub to create a blank dialog on the screen
- sub create_ok_dialog {
- my ($title_text) = @_;
- create_dialog_base($title_text);
- print_ok_right_text(0);
-
- }
-
- sub create_open_levelset_dialog {
- if ($modified_levelset == 1) {
- $modified_levelset_action = 'create_open_levelset_dialog_ok_only()';
- create_save_changes_dialog();
- } else {
- $displaying_dialog = 'ls_open';
- create_dialog('SELECT LEVELSET TO OPEN');
- $list_browser_highlight_offset = -1;
- $list_browser_file_start_offset = -1;
- display_levelset_list_browser(0,0);
- }
- }
-
- sub create_open_levelset_dialog_ok_only {
-
- $displaying_dialog = 'ls_open_ok_only';
- create_ok_dialog('SELECT LEVELSET TO OPEN');
- $list_browser_highlight_offset = -1;
- $list_browser_file_start_offset = -1;
- display_levelset_list_browser(0,0);
-
- }
-
- sub iter_rowscols(&) {
- my ($f) = @_;
- local ($::row, $::col);
- foreach $::row (0 .. $NUM_ROWS - 1) {
- foreach $::col (0 .. ($POS_1P{p1}{right_limit}-$POS_1P{p1}{left_limit})/$BUBBLE_SIZE - 1 - odd($::row)) {
- &$f;
- }
- }
- }
-
- sub save_file {
- my @contents;
- foreach my $lev (1 .. keys %bubble_hash) {
- iter_rowscols {
- if ($::col == 0) {
- ($lev == 1 && $::row == 0) or push @contents, "\n";
- odd($::row) and push @contents, " ";
- }
- push @contents, "$bubble_hash{$lev}{$::col}{$::row}";
- $::col+odd($::row) < 7 and push @contents, " ";
- };
- push @contents, "\n";
- }
- output("$FBLEVELS/$levelset_name", @contents);
- $modified_levelset = 0;
- }
-
- sub create_play_levelset_dialog {
- $displaying_dialog = 'ls_play';
- create_ok_dialog('SELECT LEVELSET TO PLAY');
- $list_browser_highlight_offset = -1;
- $list_browser_file_start_offset = -1;
- display_levelset_list_browser(0, 0);
- }
-
- sub create_save_changes_dialog {
- $modified_levelset = 0;
- #reset the modified levelset flag
- $displaying_dialog = 'ls_save_changes';
- create_dialog('SAVE CHANGES?');
-
- $rect{middle} = get_dialog_rect();
-
- # write out the instructions
- $app->print($rect{middle}->x + 25, $rect{middle}->y + $WOOD_PLANK_HEIGHT, 'THERE ARE UNSAVED CHANGES');
- $app->print($rect{middle}->x + 22, $rect{middle}->y + 35 + $WOOD_PLANK_HEIGHT, "PRESS \"OK\" TO SAVE");
- $app->print($rect{middle}->x + 22, $rect{middle}->y + 55 + $WOOD_PLANK_HEIGHT, "CHANGES AND CONTINUE");
- $app->print($rect{middle}->x + 22, $rect{middle}->y + 95 + $WOOD_PLANK_HEIGHT, "PRESS \"CANCEL\" TO CONTINUE");
- $app->print($rect{middle}->x + 22, $rect{middle}->y + 115 + $WOOD_PLANK_HEIGHT, "WITHOUT SAVING");
- }
-
- # subroutine to display to the user a list of levelsets and allow them
- # to browse through and select one of them.
- sub display_levelset_list_browser {
- my ($file_start_offset, $file_highlight_offset) = @_;
- my ($surf_file_list_background, $surf_purple_highlight, $surf_scroll_list_background, $cnt);
-
- my @levelsets = get_levelset_list();
- my $do_scroll = $file_start_offset != $list_browser_file_start_offset;
-
- if ($file_highlight_offset > @levelsets - 1
- || $file_highlight_offset == $list_browser_highlight_offset && !$do_scroll) {
- # this is the case where the user either clicks on the same
- # file that is already selected, or clicks in the file box, but
- # not on a file (for example, the user click on the second
- # file section when only one file is displayed
- return;
- }
-
- # we can display 4 files. If the offset makes us print less than 1, ignore it
- # also, make sure we don't let an offset of less than 0 go through
- if ($file_start_offset < @levelsets && $file_start_offset >= 0) {
- # save the current file offset
- $list_browser_file_start_offset = $file_start_offset;
- } else {
- # we don't need to draw anything. just exit
- return;
- }
-
- $rect{middle} = get_dialog_rect();
-
- $surf_file_list_background = SDL::Surface->new(-name => "$FPATH/gfx/file_list_background.png");
-
- $rect{list_box_src} = SDL::Rect->new(-width => $surf_file_list_background->width,
- -height => 3 * $WOOD_PLANK_HEIGHT);
-
- $rect{dialog_file_list} = SDL::Rect->new(-x => $rect{middle}->x + 9, '-y' => $rect{middle}->y + $WOOD_PLANK_HEIGHT + 37,
- -width => $rect{list_box_src}->width, -height => $rect{list_box_src}->height);
-
- $surf_purple_highlight = SDL::Surface->new(-name => "$FPATH/gfx/purple_hover.gif");
-
- $rect{purple_highlight_src} = SDL::Rect->new(-width => $surf_purple_highlight->width,
- -height => $surf_purple_highlight->height);
-
- # we only want to draw the arrows and background here once, when we first get launched
- if ($list_browser_highlight_offset == -1) {
- $surf_scroll_list_background = SDL::Surface->new(-name => "$FPATH/gfx/scroll_list_background.png");
-
- $rect{scroll_list_background_src} = SDL::Rect->new(-width => $surf_scroll_list_background,
- -height => 3 * $WOOD_PLANK_HEIGHT);
-
- $rect{scroll_list_background_dest} = SDL::Rect->new(-x => $rect{dialog_file_list}->x + $rect{dialog_file_list}->width,
- '-y' => $rect{dialog_file_list}->y,
- -width => $rect{scroll_list_background_src}->width,
- -height => $rect{scroll_list_background_src}->height);
-
- $surf_scroll_list_background->blit($rect{scroll_list_background_src}, $app, $rect{scroll_list_background_dest});
- $app->update($rect{scroll_list_background_dest});
-
- print_dialog_list_arrow_down(0);
- print_dialog_list_arrow_up(0);
- my $surface_loading = SDL::Surface->new(-name => "$FPATH/gfx/loadingpreviews.png");
-
- $surface_loading->blit(SDL::Rect->new(-width => $surface_loading->width, -height => $surface_loading->height),
- $app,
- SDL::Rect->new(-x => $rect{scroll_list_background_dest}->x + $rect{scroll_list_background_dest}->width + 7,
- '-y' => $rect{scroll_list_background_dest}->y + 20,
- -width => $surface_loading->width, -height => $surface_loading->width));
- }
-
- if ($do_scroll == 1) {
- $surf_file_list_background->blit($rect{list_box_src}, $app, $rect{dialog_file_list});
- $app->update($rect{dialog_file_list});
-
- for ($cnt = $file_start_offset; $cnt < $file_start_offset + 4; $cnt++) {
- if ($file_highlight_offset == $cnt) {
- $rect{purple_highlight_dest} = SDL::Rect->new(
- -x => $rect{middle}->x + 12,
- '-y' => $rect{dialog_file_list}->y + 10 + 25 * ($cnt - $file_start_offset),
- -width => $surf_purple_highlight->width, -height => $surf_purple_highlight->height);
-
- $surf_purple_highlight->blit($rect{purple_highlight_src}, $app, $rect{purple_highlight_dest});
- $app->update($rect{purple_highlight_dest});
- }
- $app->print($rect{middle}->x + 19, $rect{dialog_file_list}->y + 8 + 25 * ($cnt - $file_start_offset),
- uc($levelsets[$cnt]));
- }
- } else {
- # erase the old highlight
- $rect{old_highlight} = SDL::Rect->new(
- -x => $rect{middle}->x + 12,
- '-y' => $rect{dialog_file_list}->y + 10 + 25 * ($list_browser_highlight_offset - $list_browser_file_start_offset),
- -width => $surf_purple_highlight->width, -height => $surf_purple_highlight->height);
-
- $rect{erase_highlight} = SDL::Rect->new(
- -x => $rect{old_highlight}->x - $rect{dialog_file_list}->x,
- '-y' => $rect{old_highlight}->y - $rect{dialog_file_list}->y,
- -width => $surf_purple_highlight->width, -height => $surf_purple_highlight->height);
-
- # it is possible that the highlighed dude is off the screen. In this case, do not
- # call the blit, bacause there is no visible highlight to remove
- if ($list_browser_highlight_offset >= $list_browser_file_start_offset && $list_browser_highlight_offset <= $list_browser_file_start_offset + 3) {
- $surf_file_list_background->blit($rect{erase_highlight}, $app, $rect{old_highlight});
- $app->update($rect{old_highlight});
- # draw the text of the old highligted dude
- $app->print($rect{middle}->x + 19,
- $rect{dialog_file_list}->y + 8 + 25 * ($list_browser_highlight_offset - $list_browser_file_start_offset),
- uc($levelsets[$list_browser_highlight_offset]));
- }
-
- # draw the highlight
- $rect{purple_highlight_dest} = SDL::Rect->new(
- -x => $rect{middle}->x + 12,
- '-y' => $rect{dialog_file_list}->y + 10 + 25 * ($file_highlight_offset - $file_start_offset),
- -width => $surf_purple_highlight->width,
- -height => $surf_purple_highlight->height);
- $surf_purple_highlight->blit($rect{purple_highlight_src}, $app, $rect{purple_highlight_dest});
- $app->update($rect{purple_highlight_dest});
- $app->print($rect{middle}->x + 19,
- $rect{dialog_file_list}->y + 8 + 25 * ($file_highlight_offset - $file_start_offset),
- uc($levelsets[$file_highlight_offset]));
- }
-
- # set the unhighlight so the app thinks nothings highlighted and will highlight
- # the correct item in the next highlight function call
- unhighlight_option();
-
- $app->update($rect{middle});
-
- if ($file_highlight_offset != $list_browser_highlight_offset) {
- if ($list_browser_highlight_offset == -1) {
- $list_browser_highlight_offset = 0;
-
- @file_browser_screenshots = ();
- my @levelset_list = get_levelset_list();
- foreach my $levelset (@levelset_list) {
- my $surface_screenshot = SDL::Surface->new(-name => "$FPATH/gfx/level_editor.png");
- load_level($surface_screenshot, read_file($levelset));
- $file_browser_screenshots[@file_browser_screenshots] = $surface_screenshot;
- }
- }
- $list_browser_highlight_offset = $file_highlight_offset;
- display_levelset_screenshot();
- } else {
- $list_browser_highlight_offset = $file_highlight_offset;
- }
-
- $app->flip;
- }
-
- # display a scrrenshot (1/4 size) of the first level in a levelset on the current dialog
- sub display_levelset_screenshot {
- $rect{middle} = get_dialog_rect();
- $rect{screenshot} = SDL::Rect->new(-x => $POS_1P{p1}{left_limit} - 40, '-y' => 0,
- -width => $POS_1P{p1}{right_limit} - $POS_1P{p1}{left_limit} + 80,
- -height => $POS_1P{bottom_limit} - $POS_1P{init_top_limit} + 190);
- if ($SDL::VERSION >= 1.20) {
- fb_c_stuff::shrink($$app,
- $file_browser_screenshots[$list_browser_highlight_offset]->display_format,
- $rect{middle}->x + $rect{middle}->width - $rect{screenshot}->width/4 - 12,
- $rect{middle}->y + $rect{middle}->height/2 - $rect{screenshot}->height/8 - 3,
- $rect{screenshot}{-rect}, 4);
- }
- else {
- fb_c_stuff::shrink($app->{-surface},
- $file_browser_screenshots[$list_browser_highlight_offset]->display_format()->{-surface},
- $rect{middle}->x + $rect{middle}->width - $rect{screenshot}->width/4 - 12,
- $rect{middle}->y + $rect{middle}->height/2 - $rect{screenshot}->height/8 - 3,
- $rect{screenshot}{-rect}, 4);
- }
- }
-
-
- #- ----------- levels and levelsets operations ------------------------------------------
-
- # subroutine load_level
- sub load_level {
- my ($surface_tmp, %b) = @_;
- my $curr_lvl;
-
- if ($surface_tmp) {
- $curr_lvl = 1;
- } else {
- $curr_lvl = $curr_level;
- %b = %bubble_hash;
- clear_level();
- print_level_nb();
- }
-
- iter_rowscols {
- my $bub = \$b{$curr_lvl}{$::col}{$::row};
- defined($$bub) or $$bub = '-'; #- sanitize
- if ($$bub ne '-') {
- draw_bubble($$bub + 1,
- $::col * $BUBBLE_SIZE + $POS_1P{p1}{left_limit} + odd($::row)*$BUBBLE_SIZE/2,
- $::row * $ROW_SIZE + $POS_1P{init_top_limit},
- $ALPHA_BUBBLE_NO, $surface_tmp, undef, 1);
- }
- };
-
- $app->flip;
- }
-
- # subroutine to clear level off the screen
- sub clear_level {
- $rect{clear} = SDL::Rect->new(-width => $POS_1P{p1}{right_limit} - $POS_1P{p1}{left_limit},
- -height => $POS_1P{bottom_limit} - $POS_1P{init_top_limit} + $BUBBLE_SIZE,
- -x => $POS_1P{p1}{left_limit},
- '-y' => $POS_1P{init_top_limit});
-
- $background->blit($rect{clear}, $app, $rect{clear});
- $app->update;
- }
-
- sub delete_level {
-
- delete $bubble_hash{$curr_level};
-
- if ($curr_level - 1 == keys %bubble_hash) {
- $curr_level--;
- if ($curr_level == 0) {
- append_level();
- }
- } else {
- foreach my $lev ($curr_level .. keys %bubble_hash) {
- $bubble_hash{$lev} = $bubble_hash{$lev + 1};
- }
-
- delete $bubble_hash{keys %bubble_hash};
- }
-
- $modified_levelset = 1;
- }
-
- # subroutine to actually create a new levelset
- sub create_new_levelset {
-
- $levelset_name = lc($new_ls_name_text);
-
- %bubble_hash = ();
- $curr_level = 0;
- append_level();
-
- print_levelset_name();
- load_level();
- $modified_levelset = 0;
- }
-
- # subroutine to delete a levelset
- sub delete_levelset {
-
- my @levelsets = get_levelset_list();
- my $lvs_name = $levelsets[$list_browser_highlight_offset];
- unlink "$FBLEVELS/$lvs_name" or die "Can't remove $FBLEVELS/$lvs_name\n";
- remove_dialog();
-
- $levelset_name eq $lvs_name and create_deleted_current_levelset_dialog();
- }
-
- # this subroutine is mostly copied from frozen-bubble
- sub read_file {
- my ($file_name) = @_;
-
- my $row = 0;
- my $lev_number = 1;
- my %tmp_hash;
- foreach my $line (cat_("$FBLEVELS/$file_name")) {
- if ($line !~ /\S/) {
- if ($row) {
- $lev_number++;
- $row = 0;
- }
- } else {
- my $col = 0;
- foreach (split ' ', $line) {
- $tmp_hash{$lev_number}{$col}{$row} = $_;
- $col++;
- }
- $row++;
- }
- }
-
- return %tmp_hash;
-
- }
-
- # subroutine to open the levelset
- sub open_levelset {
- my (@levelsets);
- # reset the deleted_current_levelset flag in case
- # we were in that situation
-
- $deleted_current_levelset = 0;
- @levelsets = get_levelset_list();
-
- $levelset_name = $levelsets[$list_browser_highlight_offset];
- %bubble_hash = read_file($levelset_name);
- print_levelset_name();
- $curr_level = 1;
- remove_dialog();
- $modified_levelset = 0;
- }
-
-
- #- ----------- navigation in a levelset ------------------------------------------
-
- sub prev_level {
- $curr_level > 1 and $curr_level--;
- load_level();
- }
-
- sub next_level {
- $curr_level < keys %bubble_hash and $curr_level++;
- load_level();
- }
-
- sub first_level {
- $curr_level = 1;
- load_level();
- }
-
- sub last_level {
- $curr_level = keys %bubble_hash;
- load_level();
- }
-
- sub jump_to_level {
- my ($n) = @_;
- if ($n >= 1 && $n <= keys %bubble_hash) {
- $curr_level = $_[0];
- load_level();
- }
- }
-
- sub insert_level {
- for (my $lev = 1 + keys %bubble_hash; $lev > $curr_level; $lev--) {
- $bubble_hash{$lev} = $bubble_hash{$lev - 1};
- }
-
- delete $bubble_hash{$curr_level};
-
- # initialize our new level
- iter_rowscols { $bubble_hash{$curr_level}{$::col}{$::row} = '-' };
-
- load_level();
- $modified_levelset = 1;
- }
-
- sub append_level {
- $curr_level++;
- insert_level();
- }
-
- sub move_level_left {
- $curr_level > 1 or return;
- ($bubble_hash{$curr_level-1}, $bubble_hash{$curr_level}) = ($bubble_hash{$curr_level}, $bubble_hash{$curr_level-1});
- $curr_level--;
- load_level();
- $modified_levelset = 1;
- }
-
- sub move_level_right {
- $curr_level < keys(%bubble_hash) or return;
- ($bubble_hash{$curr_level+1}, $bubble_hash{$curr_level}) = ($bubble_hash{$curr_level}, $bubble_hash{$curr_level+1});
- $curr_level++;
- load_level();
- $modified_levelset = 1;
- }
-
-
- #- ----------- printing stuff ------------------------------------------
-
- sub print_cancel_text {
- my ($do_highlight) = @_;
-
- if ($displaying_dialog ne '') {
- $rect{middle} = get_dialog_rect();
-
- $rect{cancel_src} = SDL::Rect->new(-x => $rect{middle}->width - $rect{option_highlight}->width,
- '-y' => 6 * $WOOD_PLANK_HEIGHT - 4,
- -width => $rect{middle}->width/2, -height => $WOOD_PLANK_HEIGHT);
-
- $rect{cancel} = SDL::Rect->new(-x => $rect{middle}->x + $rect{middle}->width - $rect{option_highlight}->width,
- '-y' => $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT - 4,
- -width => $rect{middle}->width/2, -height => $WOOD_PLANK_HEIGHT);
-
- $surface_dialog->blit($rect{cancel_src}, $app, $rect{cancel});
- $app->update($rect{cancel});
-
- $app->print($rect{middle}->x + $rect{middle}->width - 120, $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT, 'CANCEL');
- if ($do_highlight) {
- $highlight->blit($rect{option_highlight}, $app, $rect{cancel});
- $app->update($rect{cancel});
- }
- }
- }
-
- sub print_dialog_list_arrow {
- my ($do_highlight, $type) = @_;
-
- $rect{middle} = get_dialog_rect();
-
- my $surf_list_arrow = SDL::Surface->new(-name => "$FPATH/gfx/list_arrow_$type.png");
- $rect{list_arrow_src} = SDL::Rect->new(-width => $surf_list_arrow->width, -height => $surf_list_arrow->height);
- $rect{list_arrow_dest} = SDL::Rect->new(
- '-x' => $rect{middle}->x + 4 * $rect{middle}->width/6 + 2,
- '-y' => $type eq 'up' ? $rect{dialog_file_list}->y + 2
- : $rect{dialog_file_list}->y + $rect{dialog_file_list}->height - $surf_list_arrow->height - 2,
- -width => $surf_list_arrow->width, -height => $surf_list_arrow->height);
-
- my $surf_scroll_list_background = SDL::Surface->new(-name => "$FPATH/gfx/scroll_list_background.png");
- $rect{erase_arrow} = SDL::Rect->new('-x' => $rect{list_arrow_dest}->x - $rect{scroll_list_background_dest}->x,
- '-y' => $rect{list_arrow_dest}->y - $rect{scroll_list_background_dest}->y,
- -width => $surf_list_arrow->width, -height => $surf_list_arrow->height);
-
- $surf_scroll_list_background->blit($rect{erase_arrow}, $app, $rect{list_arrow_dest});
- $app->update($rect{list_arrow_dest});
-
- $surf_list_arrow->blit($rect{list_arrow_src}, $app, $rect{list_arrow_dest});
- $app->update($rect{list_arrow_dest});
-
- if ($do_highlight) {
- $highlight->blit($rect{list_arrow_src}, $app, $rect{list_arrow_dest});
- $app->update($rect{list_arrow_dest});
- }
- }
-
- sub print_dialog_list_arrow_down {
- my ($do_highlight) = @_;
- print_dialog_list_arrow($do_highlight, 'down');
- }
-
- sub print_dialog_list_arrow_up {
- my ($do_highlight) = @_;
- print_dialog_list_arrow($do_highlight, 'up');
- }
-
- # subroutine to print out the levelset name at the top of the screen
- sub print_levelset_name {
- $rect{ls_name_erase} = SDL::Rect->new(-x => 195, '-y' => 0, -width => 445-195, -height => 35);
- $background->blit($rect{ls_name_erase}, $app, $rect{ls_name_erase});
- $app->update;
- $app->print(($background->width - SDL_TEXTWIDTH(uc($levelset_name)))/2 - 6, 7, uc($levelset_name));
- }
-
- sub print_text_generic {
- my ($do_highlight, $name, $xpos, $ypos, $text) = @_;
-
- $background->blit($rect{$name}, $app, $rect{$name});
- $app->update($rect{$name});
-
- $app->print($xpos, $ypos, $text || uc($name));
- if ($do_highlight) {
- $highlight->blit($rect{option_highlight}, $app, $rect{$name});
- $app->update($rect{$name});
- }
- }
-
- sub print_first_text {
- print_text_generic($_[0], 'first', $WOOD_WIDTH/2, $rect{first}->y + 6);
- }
-
- sub print_last_text {
- print_text_generic($_[0], 'last', 20, $rect{last}->y + 6);
- }
-
- sub print_prev_text {
- print_text_generic($_[0], 'prev', $WOOD_WIDTH/2, $rect{prev}->y + 6);
- }
-
- sub print_next_text {
- print_text_generic($_[0], 'next', 20, $rect{next}->y + 6);
- }
-
- sub print_ls_delete_text {
- print_text_generic($_[0], 'ls_delete', $rect{ls_delete}->x + 12, $rect{ls_delete}->y + 6, 'DELETE');
- }
-
- sub print_ls_new_text {
- print_text_generic($_[0], 'ls_new', $rect{ls_new}->x + $WOOD_WIDTH/2, $rect{ls_new}->y + 6, 'NEW');
- }
-
- sub print_ls_open_text {
- print_text_generic($_[0], 'ls_open', $rect{ls_open}->x + 35, $rect{ls_open}->y + 6, 'OPEN');
- }
-
- sub print_ls_save_text {
- print_text_generic($_[0], 'ls_save', $rect{ls_save}->x + $WOOD_WIDTH/2, $rect{ls_save}->y + 6, 'SAVE');
- }
-
- sub print_lvl_append_text {
- print_text_generic($_[0], 'lvl_append', $rect{lvl_append}->x + 20, $rect{lvl_append}->y + 6, 'APPEND');
- }
-
- sub print_lvl_delete_text {
- print_text_generic($_[0], 'lvl_delete', $rect{lvl_delete}->x + $WOOD_WIDTH/2, $rect{lvl_delete}->y + 6, 'DELETE');
- }
-
- sub print_lvl_insert_text {
- print_text_generic($_[0], 'lvl_insert', $rect{lvl_insert}->x + $WOOD_WIDTH/2 - 5, $rect{lvl_insert}->y + 6, 'INSERT');
- }
-
- # filename is OK == not blank or pre-existing
- sub is_ok_filename {
- length($new_ls_name_text) == 0 and return 0;
-
- lc($new_ls_name_text) eq lc($_) and return 0 foreach get_levelset_list();
-
- return 1;
- }
-
- # subroutine to get the letter pressed by the user on the keyboard
- # this subroutine is taken from frozen-bubble code
- sub keysym_to_char($) {
- my ($key) = @_;
- eval "$key eq SDLK_$_" and return uc($_) foreach @fbsyms::syms;
- }
-
- # subroutine to print the name of the new levelset in the dialog
- sub print_new_ls_name {
- my ($key) = @_;
- if ($key == SDLK_ESCAPE()) {
- if ($displaying_dialog eq 'ls_new') {
- highlight_option('cancel');
- $app->delay(200);
- remove_dialog();
- }
- } elsif (($key == SDLK_RETURN() || $key == SDLK_KP_ENTER()) && length($new_ls_name_text) > 0 && is_ok_filename() ) {
- if ($displaying_dialog eq 'ls_new') {
- highlight_option('ok');
- } elsif ($displaying_dialog eq 'ls_new_ok_only') {
- highlight_option('ok_right');
- }
- $app->delay(200);
- remove_dialog();
- create_new_levelset();
- } elsif ($key == SDLK_BACKSPACE()
- || (length($new_ls_name_text) < 14 && ($key == SDLK_KP_MINUS()
- || $key >= SDLK_KP0() && $key <= SDLK_KP9()
- || $key >= SDLK_a() && $key <= SDLK_z()
- || $key == SDLK_MINUS()
- || $key >= SDLK_0 && $key <= SDLK_9()))) {
- # first erase the previous words
- $rect{dialog_blank} = SDL::Rect->new('-y' => 2 * $WOOD_PLANK_HEIGHT,
- -width => $surface_dialog->width,
- -height => $surface_dialog->height - 3 * $WOOD_PLANK_HEIGHT);
- $rect{dialog_new} = SDL::Rect->new(-x => $background->width/2 - $surface_dialog->width/2,
- '-y' => $background->height/2 - $surface_dialog->height/2 + 2 * $WOOD_PLANK_HEIGHT,
- -width => $surface_dialog->width,
- -height => $surface_dialog->height - 3*$WOOD_PLANK_HEIGHT);
- $surface_dialog->blit($rect{dialog_blank}, $app, $rect{dialog_new});
- $app->update;
- if ($key == SDLK_BACKSPACE()) {
- chop $new_ls_name_text;
- } elsif ($key == SDLK_MINUS() || $key == SDLK_KP_MINUS()) {
- $new_ls_name_text .= '-';
- } elsif ($key >= SDLK_KP0() && $key <= SDLK_KP9()) {
- my $kp_num;
- eval("SDLK_KP$_() eq $key") and $new_ls_name_text .= $_ foreach 0..9;
- } else {
- $new_ls_name_text .= keysym_to_char($key);
- }
- $app->print($rect{dialog_new}->x + $rect{dialog_new}->width/2 - 12 * length($new_ls_name_text)/2, 210, $new_ls_name_text);
- }
-
- # if the filename is bad, unhighlight any option that is highlighted since
- # they can't do anything...
- is_ok_filename() == 0 and unhighlight_option();
-
- }
-
- # subroutine to print the ok text on the right side of the dialog
- sub print_ok_right_text {
- my ($do_highlight) = @_;
- if ($displaying_dialog ne '') {
- $rect{middle} = get_dialog_rect();
-
- $rect{cancel_src} = SDL::Rect->new(-x => $rect{middle}->width - $rect{option_highlight}->width,
- '-y' => 6 * $WOOD_PLANK_HEIGHT - 4,
- -width => $rect{middle}->width/2,
- -height => $WOOD_PLANK_HEIGHT);
-
- $rect{cancel} = SDL::Rect->new(-x => $rect{middle}->x + $rect{middle}->width - $rect{option_highlight}->width,
- '-y' => $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT - 4,
- -width => $rect{middle}->width/2,
- -height => $WOOD_PLANK_HEIGHT);
-
- $surface_dialog->blit($rect{cancel_src}, $app, $rect{cancel});
- $app->update($rect{cancel});
-
- $app->print($rect{middle}->x + $rect{middle}->width - 80, $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT, 'OK');
- if ($do_highlight) {
- $highlight->blit($rect{option_highlight}, $app, $rect{cancel});
- $app->update($rect{cancel});
- }
- }
- }
-
- sub print_ok_text {
- my ($do_highlight) = @_;
-
- if ($displaying_dialog ne '') {
- $rect{middle} = get_dialog_rect();
-
- $rect{ok_src} = SDL::Rect->new('-y' => 6 * $WOOD_PLANK_HEIGHT - 4,
- -width => $rect{middle}->width/2,
- -height => $WOOD_PLANK_HEIGHT);
-
- $rect{ok} = SDL::Rect->new(-x => $rect{middle}->x,
- '-y' => $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT - 4,
- -width => $rect{middle}->width/2,
- -height => $WOOD_PLANK_HEIGHT);
-
- $surface_dialog->blit($rect{ok_src}, $app, $rect{ok});
- $app->update($rect{ok});
-
- $app->print($rect{middle}->x + 60, $rect{middle}->y + 6 * $WOOD_PLANK_HEIGHT, 'OK');
- if ($do_highlight) {
- $highlight->blit($rect{option_highlight}, $app, $rect{ok});
- $app->update($rect{ok});
- }
- }
- }
-
- sub print_level_nb {
- my $level_sign_rect = SDL::Rect->new(-x => $POS_1P{p1}{scoresx} - 50, '-y' => $POS_1P{scoresy},
- -width => 100, -height => 25);
-
- $background->blit($level_sign_rect, $app, $level_sign_rect);
- $app->update($level_sign_rect);
-
- my $text = "$curr_level/" . keys %bubble_hash;
-
- $app->print($POS_1P{p1}{scoresx} - 12 * length($text)/2, $POS_1P{scoresy}, $text);
-
- }
-
-
- #- ----------- initialization stuff ------------------------------------------
-
- # subroutine to add specific bubble option
- sub add_bubble_option {
- my ($bubble_id, $col, $row) = @_;
- draw_bubble($bubble_id, bubble_optionx($col), bubble_optiony($row), $ALPHA_BUBBLE_NO);
- }
-
- # subroutine to add the bubble options
- sub add_bubble_options {
- my ($count, $col_count);
- # add my list of bubbles on the left
- $count = 0;
-
- while ($count < $NUM_BUBBLES_AVAIL) {
- $col_count = 0;
- while ($col_count < $BUBBLES_PER_ROW && $count < $NUM_BUBBLES_AVAIL) {
- add_bubble_option($count + 1, $col_count, floor($count/$BUBBLES_PER_ROW));
- $col_count++;
- $count++;
- }
- }
-
- if ($col_count >= $BUBBLES_PER_ROW) {
- $col_count = 0;
- }
-
- }
-
- # subroutine to add the erase option
- sub add_erase_option {
- my $erase = SDL::Surface->new(-name => "$FPATH/gfx/balls/stick_effect_7.png");
- $erase->blit(NULL, $app, $rect{erase});
- $app->update($rect{erase});
- }
-
- # subroutine to do the initial setup
- sub init_setup {
- my ($application_caller, $sdlapp) = @_;
-
- init_app($application_caller, $sdlapp);
-
- $background->blit(NULL, $app, $rect{background});
- $app->update($rect{background});
-
- add_bubble_options();
- add_erase_option();
-
- # set font
- $font = new SDL::Font("$FPATH/gfx/font.png");
-
- $app->print(5, $BUBBLE_WOOD_Y + 3, 'CHOOSE BUBBLE');
-
- # add navigation words
- $app->print(20, $NAV_WOOD_Y + 8,'NAVIGATION');
- print_prev_text(0);
- print_next_text(0);
- print_first_text(0);
- print_last_text(0);
-
- # add levelset words
- $app->print($RIGHT_WOOD_X + 30, $LEVELSET_WOOD_Y + 8, 'LEVELSET');
- print_ls_new_text(0);
- print_ls_open_text(0);
- print_ls_save_text(0);
- print_ls_delete_text(0);
-
- # add level words
- $app->print($RIGHT_WOOD_X + 45, $LEVEL_WOOD_Y + 8, 'LEVEL');
- print_lvl_insert_text(0);
- print_lvl_append_text(0);
- print_lvl_delete_text(0);
-
- # add initial bubble to draw
- change_color(1);
-
- $modified_levelset = 0;
- -d "$FBLEVELS" or mkdir "$FBLEVELS" or die "Can't create $FBLEVELS directory.\n";
- -f "$FBLEVELS/default-levelset" or cp_af("$FPATH/data/levels", "$FBLEVELS/default-levelset");
-
- %bubble_hash = read_file($levelset_name);
-
- # if inputted level is > the number of levels than reset current level to 1
- $curr_level > keys %bubble_hash and $curr_level = 1;
- load_level();
-
- SDL::WarpMouse(320, 240);
-
- print_levelset_name();
- $app->flip;
-
- $button_hold = 0;
- }
-
- # subroutine to initialize the application
- sub init_app {
- my ($application_caller, $sdlapp) = @_;
- my @rcfile_data;
-
- $app = $sdlapp;
- # we only want to check to see if we're in full screen if we're
- # running as a stand alone app. If we're running embedded in the
- # game, we'll use whatever is already set up
- if ($application_caller eq 'stand-alone') {
- @rcfile_data = cat_("$FPATH/.fbrc");
-
- if ($command_line_fullscreen == 1) {
- $app->fullscreen;
- } elsif ($rcfile_data[0] eq "\$fullscreen = 1;\n") {
- $app->fullscreen;
- }
- } else {
- # we need to set the default levelset name to "default-levelset"
- $levelset_name = 'default-levelset';
- $curr_level = 1;
- }
-
- # background image
- $background = SDL::Surface->new(-name => "$FPATH/gfx/level_editor.png");
-
- my @allrects =
- ({ name => 'background', width => $background->width, height => $background->height },
- # bubble wood rectangle (without heading part)
- { name => 'bubble_wood', x => $LEFT_WOOD_X, 'y' => $BUBBLE_WOOD_Y + $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT * ($NUM_BUBBLES_AVAIL + 1)/$BUBBLES_PER_ROW },
- { name => 'erase', x => bubble_optionx($NUM_BUBBLES_AVAIL % $BUBBLES_PER_ROW),
- 'y' => bubble_optiony(floor($NUM_BUBBLES_AVAIL / $BUBBLES_PER_ROW)),
- width => $BUBBLE_SIZE, height => $BUBBLE_SIZE },
-
- # navigation rectangles
- { name => 'prev', x => $LEFT_WOOD_X, 'y' => $NAV_WOOD_Y + $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'next', x => $LEFT_WOOD_X, 'y' => $NAV_WOOD_Y + 2 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'first', x => $LEFT_WOOD_X, 'y' => $NAV_WOOD_Y + 3 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'last', x => $LEFT_WOOD_X, 'y' => $NAV_WOOD_Y + 4 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
-
- # levelset rectangles
- { name => 'ls_new', x => $RIGHT_WOOD_X, 'y' => $LEVELSET_WOOD_Y + $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'ls_open', x => $RIGHT_WOOD_X, 'y' => $LEVELSET_WOOD_Y + 2 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'ls_save', x => $RIGHT_WOOD_X, 'y' => $LEVELSET_WOOD_Y + 3 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'ls_delete', x => $RIGHT_WOOD_X, 'y' => $LEVELSET_WOOD_Y + 4 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
-
- # level rectangles
- { name => 'lvl_insert', x => $RIGHT_WOOD_X, 'y' => $LEVEL_WOOD_Y + $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'lvl_append', x => $RIGHT_WOOD_X, 'y' => $LEVEL_WOOD_Y + 2 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
- { name => 'lvl_delete', x => $RIGHT_WOOD_X, 'y' => $LEVEL_WOOD_Y + 3 * $WOOD_PLANK_HEIGHT,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT },
-
- { name => 'bubble_option_highlight', x => 0, 'y' => 0,
- width => $BUBBLE_SIZE, height => $BUBBLE_SIZE },
- { name => 'option_highlight', x => 0, 'y' => 0,
- width => $WOOD_WIDTH, height => $WOOD_PLANK_HEIGHT }
- );
-
- $rect{$_->{name}} = SDL::Rect->new(-width => $_->{width}, -height => $_->{height},
- -x => $_->{x}, '-y' => $_->{'y'}) foreach @allrects;
-
- $highlight = SDL::Surface->new(-name => "$FPATH/gfx/hover.gif");
- $highlight->set_alpha(SDL_SRCALPHA, 0x44);
- }
-
-
- 1;
-